#include "string.h"
namespace MyString
{
	const size_t string::npos = -1;
	string::string(const char* str)
		:_size(strlen(str))
	{
		_capacity = _size;
		_str = new char[_size + 1]; //多开一个空间用来存放'\0'
		strcpy(_str, str);
	}
	string::string(size_t n, char c)
		:_size(n)
	{
		_capacity = _size;
		_str = new char[_size + 1];
		for (size_t i = 0; i < n; i++)
		{
			_str[i] = c;
		}
		_str[n] = '\0';
	}
	//string::string(const string& s)
	//{
	//	_str = new char[s._capacity + 1]; //多开一个空间用来存放'\0'
	//	strcpy(_str, s._str);
	//	_size = s._size;
	//	_capacity = s._capacity;
	//}
	string::string(const string& s)
	{
		string tmp(s.c_str());
		swap(tmp);
	}
	//string& string::operator=(const string& s) //返回当前对象的引用是为了能连线赋值
	//{
	//	if (this != &s) //防止自己给自己赋值
	//	{
	//		delete[] _str; //先将当前的内存空间释放掉
	//		_str = new char[s._capacity + 1]; //重新开辟和s一样大的空间，多开一个空间是为了存储'\0'
	//		strcpy(_str, s._str); //复制数据
	//		_size = s._size;
	//		_capacity = s._capacity;
	//	}
	//	return *this;
	//}
	//string& string::operator=(const string& s) //返回当前对象的引用是为了能连线赋值
	//{
	//	if (this != &s) //防止自己给自己赋值
	//	{
	//		char* tmp = new char[s._capacity + 1]; //先用临时指针tmp接受新开辟的空间
	//		strcpy(tmp, s._str); //如果开辟成功就将数据赋值到这个空间
	//		delete[] _str; //释放旧空间
	//		_str = tmp; //将_str指向新空间
	//		_size = s._size;
	//		_capacity = s._capacity;
	//	}
	//	return *this;
	//}
	//string& string::operator=(const string& s) //返回当前对象的引用是为了能连线赋值
	//{
	//	if (this != &s) //防止自己给自己赋值
	//	{
	//		string tmp(s);
	//		swap(_str, tmp._str);
	//		swap(_size, tmp._size);
	//		swap(_capacity, tmp._capacity);
	//	}
	//	return *this;
	//}
	string& string::operator=(string s) //返回当前对象的引用是为了能连线赋值
	{
		swap(s);
		return *this;
	}
	string::~string()
	{
		delete[] _str;
		_str = nullptr; //不要忘了将指针_str置为空，避免_str成为野指针
		_size = _capacity = 0;
	}
	void string::swap(string& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}
	const char* string::c_str() const
	{
		return _str;
	}
	size_t string::size() const
	{
		return _size;
	}
	size_t string::capacity() const
	{
		return _capacity;
	}
	bool string::empty() const
	{
		return _size == 0;
	}
	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}
	char& string::operator[](size_t pos)
	{
		assert(pos < _size); //确保pos不能越界，越界了就断言
		return _str[pos];
	}
	const char& string::operator[](size_t pos) const
	{
		assert(pos < _size); //确保pos不能越界，越界了就断言
		return _str[pos];
	}
	void string::reserve(size_t n)
	{
		//检查n是否大于原有的容量，必须大于才能调整字符串的容量
		if (n > _capacity) {
			char* tmp = new char[n + 1]; //用指针tmp去接受新开的内存空间
			strcpy(tmp, _str); //如果开辟成功，将数据拷贝到新空间
			delete[] _str; //将旧空间释放掉
			_str = tmp; //将_str指向新空间
			_capacity = n; //更改容量值
		}
	}
	void string::resize(size_t n)
	{
		if (n > _capacity) {
			reserve(n); //扩容
		}
		_size = n;
		_str[_size] = '\0';
	}
	void string::resize(size_t n, char c)
	{
		if (n > _capacity) {
			reserve(n); //扩容
		}
		for (size_t i = _size; i < n; i++)
		{
			//如果是增加长度就会进入循环，在字符串末尾插入所需数量的字符c
			_str[i] = c;
		}
		_size = n;
		_str[_size] = '\0';
	}
	string::iterator string::begin()
	{
		return _str;
	}
	string::iterator string::end()
	{
		return _str + _size;
	}
	string::const_iterator string::begin() const
	{
		return _str;
	}
	string::const_iterator string::end() const
	{
		return _str + _size;
	}
	void string::push_back(char c)
	{
		//首先检查是否需要扩容
		if (_size == _capacity) {
			//扩容
			reserve(_size == 0 ? 4 : 2 * _size);
		}
		_str[_size] = c;
		_size++;
		_str[_size] = '\0'; //最后不要忘了在末尾字符的下一个位置放\0
	}
	string& string::append(const string& str)
	{
		size_t len = str._size;
		//首先检查是否需要扩容
		if (_size + len > _capacity) {
			size_t newCapacity = 2 * _capacity;
			if (newCapacity < _size + len) {
				newCapacity = _size + len;
			}
			reserve(newCapacity);
		}
		strcpy(_str + _size, str._str); //拷贝数据，同时\0也拷贝过去了，不用手动设置\0
		_size += len;
		return *this;
	}
	string& string::append(const string& str, size_t subpos, size_t sublen)
	{
		size_t len = str._size;
		assert(subpos < len); //检查subpos是否合法
		if (subpos + sublen >= len) {
			append(str._str + subpos); //复用append(const char* s)
		}
		else {
			append(str._str + subpos, sublen); //复用append(const char* s, size_t n)
		}
		return *this;
	}
	string& string::append(const char* s)
	{
		size_t len = strlen(s);
		if (_size + len > _capacity) {
			size_t newCapacity = 2 * _capacity;
			if (newCapacity < _size + len) {
				newCapacity = _size + len;
			}
			reserve(newCapacity);
		}
		strcpy(_str + _size, s);
		_size += len;
		return *this;
	}
	string& string::append(const char* s, size_t n)
	{
		size_t len = strlen(s);
		if (n > len) {
			//如果n大于待插入的字符串长度，则赋值为该字符串的长度值
			n = len;
		}
		//检查扩容
		if (_size + n > _capacity) {
			size_t newCapacity = 2 * _capacity;
			if (newCapacity < _size + n) {
				newCapacity = _size + n;
			}
			reserve(newCapacity);
		}
		for (size_t i = 0; i < n; i++)
		{
			_str[_size++] = s[i];
		}
		_str[_size] = '\0'; //需要手动设置\0
		return *this;
	}
	string& string::append(size_t n, char c)
	{
		//检查扩容
		if (_size + n > _capacity) {
			size_t newCapacity = 2 * _capacity;
			if (newCapacity < _size + n) {
				newCapacity = _size + n;
			}
			reserve(newCapacity);
		}
		for (size_t i = 0; i < n; i++)
		{
			_str[_size + i] = c;
		}
		_size += n;
		_str[_size] = '\0';//手动设置\0
		return *this;
	}
	string& string::operator+=(const string& str)
	{
		append(str);
		return *this;
	}
	string& string::operator+=(const char* s)
	{
		append(s);
		return *this;
	}
	string& string::operator+=(char c)
	{
		push_back(c);
		return *this;
	}
	string& string::insert(size_t pos, const char* s)
	{
		assert(pos <= _size);
		size_t len = strlen(s);
		if (_size + len > _capacity) {
			size_t newCapacity = 2 * _capacity;
			if (newCapacity < _size + len) {
				newCapacity = _size + len;
			}
			reserve(newCapacity);
		}
		size_t end = _size + len;
		while (end >= pos + len)
		{
			_str[end] = _str[end - len];
			end--;
		}
		for (size_t i = 0; i < len; i++)
		{
			_str[pos + i] = s[i];
		}
		_size += len;
		return *this;
	}
	string& string::insert(size_t pos, const string& str)
	{
		insert(pos, str._str); //复用
		return *this;
	}
	string& string::insert(size_t pos, char c)
	{
		assert(pos <= _size);
		if (_size == _capacity) {
			reserve(_size == 0 ? 4 : 2 * _size);
		}
		size_t end = _size + 1;
		while (end >= pos + 1)
		{
			_str[end] = _str[end - 1];
			end--;
		}
		_str[pos] = c;
		_size++;
		return *this;
	}
	string& string::insert(size_t pos, size_t n, char c)
	{
		assert(pos <= _size);
		if (_size + n > _capacity) {
			size_t newCapacity = 2 * _capacity;
			if (newCapacity < _size + n) {
				newCapacity = _size + n;
			}
			reserve(newCapacity);
		}
		size_t end = _size + n;
		while (end >= pos + n)
		{
			_str[end] = _str[end - n];
			end--;
		}
		for (size_t i = 0; i < n; i++)
		{
			_str[pos + i] = c;
		}
		_size += n;
		return *this;
	}
	string& string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);
		if (len >= _size - pos) {
			_size = pos;
			_str[_size] = '\0';
		}
		else {
			size_t end = pos + len;
			while (end <= _size)
			{
				_str[end - len] = _str[end];
				end++;
			}
			_size -= len;
		}
		return *this;
	}
	size_t string::find(char c, size_t pos) const
	{
		assert(pos < _size);
		for (size_t i = pos; i < _size; i++)
		{
			if (_str[i] == c) {
				return i;
			}
		}
		return npos;
	}
	size_t string::find(const char* s, size_t pos) const
	{
		assert(pos < _size);
		const char* ptr = strstr(_str + pos, s);
		if (ptr == nullptr) {
			return npos;
		}
		return ptr - _str;
	}
	void swap(string& s1, string& s2)
	{
		s1.swap(s2);
	}
	string operator+(const string& s1, const string& s2)
	{
		string tmp(s1);
		tmp += s2;
		return tmp;
	}
	string operator+(const string& s1, const char* str)
	{
		string tmp(s1);
		tmp += str;
		return tmp;
	}
	string operator+(const string& s1, char c)
	{
		string tmp(s1);
		tmp.push_back(c);
		return tmp;
	}
	bool operator==(const string& lhs, const string& rhs)
	{
		return strcmp(lhs.c_str(), rhs.c_str()) == 0;
	}
	bool operator!=(const string& lhs, const string& rhs)
	{
		return !(lhs == rhs);
	}
	bool operator>=(const string& lhs, const string& rhs)
	{
		return !(lhs < rhs);
	}
	bool operator<=(const string& lhs, const string& rhs)
	{
		return !(lhs > rhs);
	}
	bool operator>(const string& lhs, const string& rhs)
	{
		return strcmp(lhs.c_str(), rhs.c_str()) > 0;
	}
	bool operator<(const string& lhs, const string& rhs)
	{
		return strcmp(lhs.c_str(), rhs.c_str()) < 0;
	}
	ostream& operator<< (ostream& os, const string& str)
	{
		for (auto& e : str)
		{
			os << e;
		}
		return os;
	}
	istream& operator>> (istream& is, string& str)
	{
		str.clear();//清空字符串
		char buff[256];//定义缓冲区
		char ch = is.get();//从输入流中获取一个字符
		int i = 0;
		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			if (i == 255) {
				buff[i] = '\0'; //不要忘了在字符串末尾给\0
				str += buff;
				i = 0;
			}
			ch = is.get();//从输入流中获取一个字符
		}
		if (i) {
			buff[i] = '\0';
			str += buff;
		}
		return is;
	}
	istream& getline(istream& is, string& str, char delim)
	{
		str.clear();//清空字符串
		char buff[256];//定义缓冲区
		char ch = is.get();//从输入流中获取一个字符
		int i = 0;
		while (ch != delim)
		{
			buff[i++] = ch;
			if (i == 255) {
				buff[i] = '\0';//不要忘了在字符串末尾给\0
				str += buff;
				i = 0;
			}
			ch = is.get();//从输入流中获取一个字符
		}
		if (i) {
			buff[i] = '\0';
			str += buff;
		}
		return is;
	}
}
